package com.github.florent37.mylittlecanvas.animation;

import com.github.florent37.mylittlecanvas.shape.Shape;
import ohos.agp.animation.AnimatorValue;

public class ShapeAnimation<S extends Shape> {
    protected final S shape;

    public ShapeAnimation(S shape) {
        this.shape = shape;
    }

    protected float[] insertAtFirst(float value, float[] values) {
        final float[] newValues = new float[values.length + 1];
        newValues[0] = value;
        for (int i = 0; i < values.length; i++) {
            newValues[i + 1] = values[i];
        }
        return newValues;
    }

    protected int[] insertAtFirst(int value, int[] values) {
        final int[] newValues = new int[values.length + 1];
        newValues[0] = value;
        for (int i = 0; i < values.length; i++) {
            newValues[i + 1] = values[i];
        }
        return newValues;
    }

    public AnimatorValue alpha(final float... alpha) {
        final AnimatorValue animatorValue = new AnimatorValue();
        animatorValue.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                shape.setAlpha(AnimatorValueUtils.getAnimatedValue(v, alpha));
            }
        });
        return animatorValue;
    }

    public AnimatorValue alphaTo(final float... values) {
        return alpha(insertAtFirst(shape.getAlpha(), values));
    }

    public AnimatorValue alphaBy(final float... values) {
        final float[] newValues = new float[values.length];
        final float alpha = shape.getAlpha();
        for (int i = 0; i < values.length; i++) {
            newValues[i] = values[i] * alpha;
        }
        return alpha(newValues);
    }

    public AnimatorValue color(final int... color) {
        final AnimatorValue animatorValue = new AnimatorValue();
        animatorValue.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                shape.setColor(AnimatorValueUtils.getAnimatedColor(v, color));
            }
        });
        return animatorValue;
    }

    public AnimatorValue colorTo(final int... values) {
        return color(insertAtFirst(shape.getColor(), values));
    }

    public AnimatorValue strokeWidthTo(final float... strokeWidth) {
        final AnimatorValue animatorValue = new AnimatorValue();
        animatorValue.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                shape.setStrokeWidth(AnimatorValueUtils.getAnimatedValue(v, insertAtFirst(shape.getStrokeWidth(), strokeWidth)));
            }
        });
        return animatorValue;
    }

    public AnimatorValue rotation(final float... values) {
        final AnimatorValue animatorValue = new AnimatorValue();
        animatorValue.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                shape.setRotation(AnimatorValueUtils.getAnimatedValue(v, values));
            }
        });
        return animatorValue;
    }

    public AnimatorValue rotationTo(final float... values) {
        return rotation(insertAtFirst(shape.getRotation(), values));
    }

    public AnimatorValue rotationBy(final float... values) {
        final float[] newValues = new float[values.length];
        final float rotation = shape.getRotation();
        for (int i = 0; i < values.length; i++) {
            newValues[i] = values[i] * rotation;
        }
        return rotation(newValues);
    }

    @Deprecated
    public AnimatorValue scale(final float... values) {
        final AnimatorValue animatorValue = new AnimatorValue();
        animatorValue.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                shape.setScale(AnimatorValueUtils.getAnimatedValue(v, values));
            }
        });
        return animatorValue;
    }

    @Deprecated
    public AnimatorValue scaleTo(final float... values) {
        return scale(insertAtFirst(shape.getScale(), values));
    }

    @Deprecated
    public AnimatorValue scaleBy(final float... values) {
        final float[] newValues = new float[values.length];
        final float scale = shape.getScale();
        for (int i = 0; i < values.length; i++) {
            newValues[i] = values[i] * scale;
        }
        return scale(newValues);
    }
}
